package org.codehaus.activemq.web;

import java.io.IOException;
import java.io.PrintWriter;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.activemq.message.ActiveMQDestination;

public class MessageServlet extends MessageServletSupport
{
  private static final Log log = LogFactory.getLog(MessageServlet.class);

  private String readTimeoutParameter = "readTimeout";
  private long defaultReadTimeout = -1L;
  private long maximumReadTimeout = 30000L;

  public void init(ServletConfig servletConfig) throws ServletException {
    super.init(servletConfig);
    String name = servletConfig.getInitParameter("defaultReadTimeout");
    if (name != null) {
      this.defaultReadTimeout = asLong(name);
    }
    name = servletConfig.getInitParameter("maximumReadTimeout");
    if (name != null)
      this.maximumReadTimeout = asLong(name);
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException
  {
    try
    {
      WebClient client = getWebClient(request);

      String text = getPostedMessageBody(request);

      Destination destination = getDestination(client, request);

      log.info("Sending message to: " + ActiveMQDestination.inspect(destination) + " with text: " + text);

      TextMessage message = client.getSession().createTextMessage(text);
      appendParametersToMessage(request, message);
      client.send(destination, message);

      response.setHeader("messageID", message.getJMSMessageID());
      response.setStatus(200);
    }
    catch (JMSException e) {
      throw new ServletException("Could not post JMS message: " + e, e);
    }
  }

  protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException
  {
    try
    {
      WebClient client = getWebClient(request);

      Destination destination = getDestination(client, request);

      long timeout = getReadTimeout(request);

      log.info("Receiving message from: " + ActiveMQDestination.inspect(destination) + " with timeout: " + timeout);

      MessageConsumer consumer = client.getConsumer(destination);

      Message message = null;

      synchronized (consumer) {
        if (timeout == 0L) {
          message = consumer.receiveNoWait();
        }
        else {
          message = consumer.receive(timeout);
        }
      }

      log.info("HTTP GET servlet done! message: " + message);

      sendMessageResponse(request, response, message);
    }
    catch (JMSException e) {
      throw new ServletException("Could not post JMS message: " + e, e);
    }
  }

  protected void doDelete(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException
  {
    try
    {
      WebClient client = getWebClient(request);

      Destination destination = getDestination(client, request);

      MessageConsumer consumer = client.getConsumer(destination);

      Message message = null;

      synchronized (consumer) {
        message = consumer.receiveNoWait();
      }

      sendMessageResponse(request, response, message);
    }
    catch (JMSException e) {
      throw new ServletException("Could not post JMS message: " + e, e);
    }
  }

  protected void sendMessageResponse(HttpServletRequest request, HttpServletResponse response, Message message) throws JMSException, IOException {
    if (message == null) {
      response.setStatus(204);
    }
    else {
      String type = getContentType(request);
      if (type != null) {
        response.setContentType(type);
      }
      setResponseHeaders(response, message);
      if ((message instanceof TextMessage)) {
        TextMessage textMsg = (TextMessage)message;
        response.getWriter().print(textMsg.getText());
      }
      else if ((message instanceof ObjectMessage)) {
        ObjectMessage objectMsg = (ObjectMessage)message;
        Object object = objectMsg.getObject();
        response.getWriter().print(object.toString());
      }
      response.setStatus(200);
    }
  }

  protected String getContentType(HttpServletRequest request)
  {
    String value = request.getParameter("xml");
    if ((value != null) && ("true".equalsIgnoreCase(value))) {
      return "text/xml";
    }
    return null;
  }

  protected void setResponseHeaders(HttpServletResponse response, Message message) throws JMSException {
    response.setHeader("destination", message.getJMSDestination().toString());
    response.setHeader("id", message.getJMSMessageID());
  }

  protected long getReadTimeout(HttpServletRequest request)
  {
    long answer = this.defaultReadTimeout;

    String name = request.getParameter(this.readTimeoutParameter);
    if (name != null) {
      answer = asLong(name);
    }
    if ((answer < 0L) || (answer > this.maximumReadTimeout)) {
      answer = this.maximumReadTimeout;
    }
    return answer;
  }
}